﻿using System;
using System.Collections.Generic;
using System.Linq;
using BearUtil.Hidden;
using UnityEngine;
using XNode;

// 熊熊组建ʕ•㉨•ʔ
namespace BearUtil
{
    /// <summary>
    /// 剧情内包含的对话
    /// </summary>
    [Serializable, CreateAssetMenu(fileName = "NewDialog", menuName = "Story&Dialog/Create Dialog"),
    RequireNode(typeof(StartNode), typeof(EndNode))]
    public class DialogGraph : XNode.NodeGraph, ICustomGraph
    {
        /// <summary>
        /// 关联 dialogNode
        /// </summary>
        public Node owner;
        
        // 编辑器上一次停留位置
        [HideInInspector]
        public Vector2 LastFocusPosition;

        public override Node AddNode(Type type)
        {
            Node node = null; 
            // 设置 index
            switch (type.Name)
            {
                case "TalkNode":
                    node = base.AddNode(type);
                    TalkNode tn = (node as TalkNode);
                    if (tn == null)
                        return node;
                    var config = (owner as DialogNode).basic;
                    tn.FontSpeed = (int)config.audioData.FontSpeed;
                    tn.VoicClip = config.audioData.SFX == null ? "": config.audioData.SFX.name;
                    break;
                default:
                    node = base.AddNode(type);
                    break;
            }
            
            UpdateData();
            
            node.name = this.name + "_" + node.GetType().Name + "_" + node.GetHashCode();
            return node;
        }
        
        private List<BearNode> _close;
        public void UpdateData()
        {
            if (nodes == null || nodes.Count <= 1)
                return;
            
            var endNode = nodes[1] as BearNode;
            // sortCount = 1;
            if (_close == null)
                _close = new List<BearNode>();
            _close.Clear();
            
            sortNodeIndex(endNode);

            endNode.index = _close.Count * 100;
            for (int i = 0; i < _close.Count; i++)
            {
                var node = _close[i];
                node.index = (_close.Count - i - 1) * 100;

                var lastNode = node.GetLast();
                if (lastNode != null)
                {
                    var ops = lastNode.Ports.Where(p => p.IsOutput)?.First();
                    if (ops == null)
                    {
                        Debug.LogError("[DialogGraph] error output ports");
                        return;
                    }
                    
                    // 获取同级节点
                    var connections = ops.GetConnections();
                    for (int j = 1; j < connections.Count; j++)
                    {
                        if (node != connections[j].node)
                            (connections[j].node as BearNode).index = node.index + j;
                    }
                }
            }
        }
        
        private void sortNodeIndex(BearNode nextNode)
        {
            if (nextNode == null)
                return;
            
            // input port 
            var input = nextNode.GetLast();
            if (input != null && !_close.Contains(input))
            {
                
                _close.Add(input);
                sortNodeIndex(input);
                
                // sortCount++;
                // bear.index = sortCount;

                // foreach (var nodePort in input.GetConnections())
                // {
                //     var bear = (nodePort.node as BearNode);
                //     if (_close.Contains(bear))
                //         continue;
                //         
                //     sortNodeIndex((nodePort.node as BearNode));
                //     _close.Add(bear);
                // }
            }
            else
            {
                var name = nextNode.GetType().Name;
                if (!name.Contains("StartNode") && !name.Contains("EndNode"))
                    Debug.LogError("[DialogGraph] link error");
                return;
            }
        }

        // 输出 Excel 数据
        public void OutputData()
        {
            DialogNode dialog = owner as DialogNode;
            List<DialogData> datas = new List<DialogData>();

            if (dialog == null)
            {
                Debug.LogError("数据错误： " + name);
                return;
            }

            UpdateData();
            // filename
            string dialog_id = dialog.basic.id;
            for (int i = 0; i < nodes.Count(); i++)
            {
                var node = nodes[i] as BearNode;
                if (node == null)
                {
                    Debug.LogError("Error BearNode Data: " + i + ":" + name);
                    continue;
                }

                 if (!node.NoInputLink() || node.OutputData)
                 {
                     DialogDataFormat.SetData(out DialogData data, node);
                     datas.Add(data);  
                 }
            }
            
            // 输出 scriptableObject 数据
            var excelData = ExcelDataGenerator.GenerateExcelData<DialogData>(datas);
            if (excelData == null)
                return;
            
            excelData.sheetName = $"dialogue_{(owner.graph as StoryGraph).basic.id}_{(owner as DialogNode).basic.id}";
            var storyGraph = (owner.graph as StoryGraph);
            string fileName = $"dialogue_{storyGraph.basic.id}_{dialog.basic.id}";
            Utils.CreateScriptableObject(excelData, ExcelDataGenerator.Instance.ExcelDataPath, fileName);
            
            // 增加文件夹
            string filePath = ExcelDataGenerator.Instance.OutputExcelFold + "/" + owner.graph.name;
            ExcelEdit.WriteExcel(excelData, filePath);
        }

        public void CoverDataToOld()
        {
            // action node transform
            for (int i = 0; i < nodes.Count(); i++)
            {
                var node = nodes[i] as BearNode;
                if (node == null)
                {
                    Debug.LogError("Error BearNode Data: " + i + ":" + name);
                    continue;
                }

                if (!node.NoInputLink() || node.GetType().Name.Equals("StartNode"))
                {
                    node.Transform();
                }
            }
        }
    }
}
